<?php
/***********************************************************************
 * @package     IvanEngine
 * @subpackage  Core
 * @author      Ivan <ivanzx@msn.com>
 * @created     2010-06-15
 ***********************************************************************/
if(defined("IVANENGINE_CORE_PRINTER"))
    die("Redefinition macro in :".__FILE__."(".__LINE__.")");
define("IVANENGINE_CORE_PRINTER", true);

require_once (dirname(__FILE__).'/Common.php');
require_once (dirname(__FILE__).'/STL/Tree.php');

class CPrinterNode extends CTree
{
    protected   $m_content      = null;
    protected   $m_attrMap      = null;
    protected   $m_isPairTag    = true;
    protected   $m_tagIsWarp    = true;
        
    public function __construct($name, $isPairTag = false, $tagIsWarp = false)
    {
        parent::__construct($name);
        $this->m_content    = new CString();
        $this->m_attrMap    = new CMap();
        $this->m_isPairTag  = $isPairTag;
        $this->m_tagIsWarp  = $tagIsWarp;
    }
    
    public function __destruct()
    {
        unset($this->m_content);
        unset($this->m_attrMap);
        parent::__destruct();
    }
    
    public function SetAttribute($name, $value)
    {
        if( !$this->m_isPairTag ){
            CLog::Get()->Warning('The PrinterNode['.$this->GetName().
                '] is not tag, can not set attribute.');
            return;
        }
        if( $this->m_attrMap->Has($name) )
        {
            $this->m_attrMap->Set($name, $value);
        }else{
            $this->m_attrMap->Add($name, $value);
        }
    }
    
    public function SetAttributes(CMap $attributes)
    {
        if( !$this->m_isPairTag ){
            CLog::Get()->Warning('The PrinterNode['.$this->GetName().
                '] is not tag, can not set attributes.');
            return;
        }
        if( $this->m_isPairTag )
        {
            $this->m_attrMap    = $attributes;
        }
    }
    
    public function SetContent($content)
    {
        $this->m_content->Set($content);
    }
    
    public function AddContent($content)
    {
        $this->m_content->Cat($content);
    }
    
    public function GetContent()
    {
        $result = '';
            
        $it = $this->m_childMap->Begin();
        for( ; !$it->IsEnd(); $it->Next() )
        {
            $signStr= '<!--{{'.$it->Value()->GetName().'}}-->';
            $content= CStringHelper::ConvertWarp($this->m_content->Get());
            if( CStringHelper::FindFirstOf($signStr, $content) != CString::npos )
            {
                $this->m_content->Replace($signStr, $it->Value()->GetContent().$signStr);
            }else{
                $result .= $it->Value()->GetContent();
            }
        }
        
        if( $this->m_isPairTag )
        {
            if( $this->GetChildCount() <= 0 && $this->m_content->Length() == 0)
                return '';
            $attributes = '';
            $it = $this->m_attrMap->Begin();
            for( ; !$it->IsEnd(); $it->Next() )
            {
                if( is_numeric($it->Value()) )
                {
                    $attributes .= ' '.$it->Key().'='.$it->Value();
                }
                else
                {
                    $attributes .= ' '.$it->Key().'="'.$it->Value().'"';
                }
            }
            
            if( $this->m_tagIsWarp )
            {
                $result = '<'.$this->GetName().$attributes.'>'.M_WARP.
                    $this->m_content->Get().$result.
                    '</'.$this->GetName().'>'.M_WARP;
            }
            else
            {
                $result = '<'.$this->GetName().$attributes.'>'.
                    $this->m_content->Get().$result.
                    '</'.$this->GetName().'>'.M_WARP;
            }
        }else{
            $result = $this->m_content->Get().$result.M_WARP;
        }
        
        return $result;
    }
}

class CPrinter extends CSingleton
{
    protected $m_root       = null;
    static protected $m_this= null;
    public function __construct()
    {
        parent::__construct();
    }
    
    public function __destruct()
    {
        unset($this->m_root);
        parent::__destruct();
    }
    
    static public function Get()
    {
        if( self::$m_this == null )
        {
            parent::StartSingleton();
            self::$m_this = new CPrinter();
            parent::EndSingleton();
        }
        return self::$m_this;
    }
    
    public function Initialize()
    {
        $this->m_root   = new CPrinterNode('root');
    }
    
    public function & GetRoot()
    {
        return  $this->m_root;
    }
 
    public function Render()
    {
        CResponse::Get()->SetContent($this->m_root->GetContent());
    }
}

?>
